"""
Utilities to make it easy to put together forms.
"""
_author_ = 'pablo@google.com'

import datetime
import time

####################################################################
def StringToDate(date_str):
  """Convert YYYY-MM-DD to date."""
  format = '%Y-%m-%d'
  try:
    return datetime.date(*time.strptime(date_str.strip(), format)[0:3])
  except:
    raise ValueError('Bad format for %s date: "%s"' % (format, date_str))


VALIDATION_DATA_TYPES = [
  'radio',    # value must be in value_choices
  'select',   #  "   "    "
  'date',     # value format must be YYYY-MM-DD
  ]

####################################################################
class Field(object):
  """Tuple for fields in an html form. Useful in django templates.

  The format_fields.html template reads from a list of Field objects
  and expands it into an html form. For example,

  fields = [Field('given_name', 'Patient given name'),
            Field('family_name', 'Patient family name',
                  extra_params=['disabled', 'value="Smith"'])]

  will be expanded into 

  <p>Patient given name<br> 
        <input type="text" name="given_name"/></p> 
  <p>Patient family name<br> 
        <input type="text" name="family_name"
         disabled value="Smith"/></p>

  Radio buttons are handled a little differently, due to them being a
  *set* of interacting inputs. When type='radio', the values are taken
  from the button_values list. If any of the value param matches any
  of the button_values, the corresponding button is interpreted as
  'checked'.
  """

  def __init__(self, name, text, help_text='',
               type='text',
               value=None,
               value_choices=None,  # a list
               extra_params=None,   # a list
               data_type=None,      # what type we'll validate against
               required=False,
               error=False, error_message=None):
    """Constructor"""

    self.name = name
    self.text = text
    self.help_text = help_text
    self.type = type
    self.value = value
    self.value_choices = value_choices
    self.extra_params = extra_params
    self.data_type = data_type
    self.required = required
    self.error = error
    self.error_message = error_message

    if data_type and not data_type in VALIDATION_DATA_TYPES:
      raise ValueError('Bad data type in Field constructor: %s' % data_type)

  #########################################################
  def Validate(self):
    """Check that the value we've got is valid for the data_type."""
    self.error = False

    if not self.value and self.required:
      self.error = True
      self.error_message = 'Missing required value'
    elif self.data_type == 'date':
      try:
        StringToDate(self.value)
      except ValueError:
        self.error = True
        self.error_message = 'Unable to parse date - use format YYYY-MM-DD'
    elif self.data_type == 'radio' or self.data_type == 'select':
      if not self.value in self.value_choices:
        self.error = True
        self.error_message = 'Invalid selection: %s' % self.value

    return not self.error
                 
    
